//
// Created by pzw on 24-3-1.
//

#include "TreeMap.h"

template<typename K, typename V, typename Compare>
void TreeMap<K, V, Compare>::clear() {
    map->clear();
}

template<typename K, typename V, typename Compare>
TreeMap<K, V, Compare> TreeMap<K, V, Compare>::clone() const {
    return TreeMap<K, V, Compare>(map->key_comp());
}

template<typename K, typename V, typename Compare>
Compare TreeMap<K, V, Compare>::comparator() const {
    return map->key_comp();
}

template<typename K, typename V, typename Compare>
bool TreeMap<K, V, Compare>::containsKey(const K &key) const {
    return map->find(key) != map->end();
}

template<typename K, typename V, typename Compare>
bool TreeMap<K, V, Compare>::containsValue(const V &value) const {
    for (const auto &pair: map) {
        if (pair.second == value) {
            return true;
        }
    }
    return false;
}

template<typename K, typename V, typename Compare>
std::set<std::pair<K, V>> TreeMap<K, V, Compare>::entrySet() {
    return std::set<std::pair<K, V>>(map->begin(), map->end());
}

template<typename K, typename V, typename Compare>
std::pair<K, V> TreeMap<K, V, Compare>::firstEntry() {
    return *map->begin();
}

template<typename K, typename V, typename Compare>
K TreeMap<K, V, Compare>::firstKey() {
    return map->begin()->first;
}

template<typename K, typename V, typename Compare>
std::pair<K, V> TreeMap<K, V, Compare>::floorEntry(const K &key) {
    auto it = map->lower_bound(key);
    if (it == map->begin() || (it != map->end() && it->first != key)) {
        --it;
    }
    return *it;
}

template<typename K, typename V, typename Compare>
K TreeMap<K, V, Compare>::floorKey(const K &key) {
    return floorEntry(key).first;
}

template<typename K, typename V, typename Compare>
V TreeMap<K, V, Compare>::get(const K &key) {
    return (*map)[key];
}

template<typename K, typename V, typename Compare>
V TreeMap<K, V, Compare>::operator[](const K &key) {
    return (*map)[key];
}

template<typename K, typename V, typename Compare>
std::map<K, V> TreeMap<K, V, Compare>::headMap(const K &toKey) {
    return std::map<K, V>(map->begin(), map->lower_bound(toKey));
}

template<typename K, typename V, typename Compare>
std::map<K, V> TreeMap<K, V, Compare>::higherEntry(const K &key) {
    auto it = map->upper_bound(key);
    if (it != map->end()) {
        return *it;
    }
    return std::pair<K, V>();
}

template<typename K, typename V, typename Compare>
K TreeMap<K, V, Compare>::higherKey(const K &key) {
    return higherEntry(key).first;
}

template<typename K, typename V, typename Compare>
std::set<K> TreeMap<K, V, Compare>::keySet() {
    std::set<K> keys;
    for (const auto &pair: map) {
        keys.insert(pair.first);
    }
    return keys;
}

template<typename K, typename V, typename Compare>
std::pair<K, V> TreeMap<K, V, Compare>::lastEntry() {
    return *map->rbegin();
}

template<typename K, typename V, typename Compare>
K TreeMap<K, V, Compare>::lastKey() {
    return map->rbegin()->first;
}

template<typename K, typename V, typename Compare>
std::pair<K, V> TreeMap<K, V, Compare>::lowerEntry(const K &key) {
    auto it = map->lower_bound(key);
    if (it != map->begin()) {
        --it;
    }
    return *it;
}

template<typename K, typename V, typename Compare>
K TreeMap<K, V, Compare>::lowerKey(const K &key) {
    return lowerEntry(key).first;
}

template<typename K, typename V, typename Compare>
std::set<K> TreeMap<K, V, Compare>::navigableKeySet() {
    std::set<K> keys;
    for (const auto &pair: map) {
        keys.insert(pair.first);
    }
    return keys;
}

template<typename K, typename V, typename Compare>
std::pair<K, V> TreeMap<K, V, Compare>::pollFirstEntry() {
    std::pair<K, V> first = *map->begin();
    map->erase(map->begin());
    return first;
}

template<typename K, typename V, typename Compare>
std::pair<K, V> TreeMap<K, V, Compare>::pollLastEntry() {
    std::pair<K, V> last = *map->rbegin();
    map->erase(--map->end());
    return last;
}

template<typename K, typename V, typename Compare>
V TreeMap<K, V, Compare>::put(const K &key, const V &value) {
    V oldValue = (*map)[key];
    (*map)[key] = value;
    return oldValue;
}

template<typename K, typename V, typename Compare>
void TreeMap<K, V, Compare>::putAll(const std::map<K, V> &m) {
    map->insert(m.begin(), m.end());
}

template<typename K, typename V, typename Compare>
V TreeMap<K, V, Compare>::remove(const K &key) {
    V value = (*map)[key];
    map->erase(key);
    return value;
}

template<typename K, typename V, typename Compare>
int TreeMap<K, V, Compare>::size() {
    return map->size();
}

template<typename K, typename V, typename Compare>
std::map<K, V> TreeMap<K, V, Compare>::subMap(const K &fromKey, bool fromInclusive, const K &toKey, bool toInclusive) {
    auto from = map->lower_bound(fromKey);
    auto to = map->upper_bound(toKey);
    if (!fromInclusive) {
        if (from != map->end() && from->first == fromKey) {
            ++from;
        }
    }
    if (!toInclusive) {
        if (to != map->end() && to->first == toKey) {
            --to;
        }
    }
    return std::map<K, V>(from, to);
}

template<typename K, typename V, typename Compare>
std::map<K, V> TreeMap<K, V, Compare>::tailMap(const K &fromKey) {
    return std::map<K, V>(map->lower_bound(fromKey), map->end());
}

template<typename K, typename V, typename Compare>
std::map<K, V> TreeMap<K, V, Compare>::headMap(const K &toKey, bool inclusive) {
    auto to = map->upper_bound(toKey);
    if (!inclusive) {
        if (to != map->end() && to->first == toKey) {
            --to;
        }
    }
    return std::map<K, V>(map->begin(), to);
}

template<typename K, typename V, typename Compare>
std::set<V> TreeMap<K, V, Compare>::values() {
    std::set<V> valSet;
    for (const auto &pair: *map) {
        valSet.insert(pair.second);
    }
    return valSet;
}

int TreeMap_main() {
    auto *treeMap = new TreeMap<int, std::string, std::less<>>(
            new std::map<int, std::string, std::less<>>()
    );
    const std::less<> &comp = std::less<>();
    auto *treeMap2 = new TreeMap<int, std::string, std::less<>>(comp);
    TreeMap<int, std::string, std::less<>> treeMap3(comp);
    TreeMap<int, std::string, std::less<>> treeMap4(
            new std::map<int, std::string, std::less<>>()
    );
    for (int i = 0; i < 8; ++i) {
        treeMap->put(8, std::to_string(8));
        treeMap2->put(8, std::to_string(8));
        treeMap3.put(8, std::to_string(8));
        treeMap4.put(8, std::to_string(8));
    }

    const std::string &x = treeMap->get(0);
    const std::string &x2 = (*treeMap)[0];
    const std::string &x3 = (*treeMap).get(0);
    std::cout << "TreeMap_main: treeMap.get(0)=" << x << std::endl;
    std::cout << "TreeMap_main: treeMap[0]=" << x2 << std::endl;
    std::cout << "TreeMap_main: (*treeMap).get(0)=" << x3 << std::endl;

    (*treeMap).comparator();
    (*treeMap).remove(7);

    const std::set<std::pair<int, std::string>> &pairSet = (*treeMap).entrySet();
    std::_Rb_tree_const_iterator<std::pair<int, std::string>> k;
    for (k = pairSet.begin(); k != pairSet.end(); k++) {
        std::cout << "TreeMap_main: k.first=" << k->first << ", k.second=" << k->second << std::endl;
    }

    const std::set<std::string> &values = (*treeMap).values();
    std::_Rb_tree_const_iterator<std::string> m;
    for (m = values.begin(); m != values.end(); m++) {
        std::cout << "TreeMap_main: m.c_str=" << m->data() << std::endl;
    }

    delete treeMap;
    delete treeMap2;
    return 0;
}